﻿/*********************************************
 创建者：  george
 创建时间：2016-11-12
 功能说明：登陆管理
 ********************************************/
using com.nm;
using com.nm.ApiServer;
using com.nm.ApiServer.Attributes;
using com.nm.Attributes;
using com.nm.db.Models.Systems;
using com.nm.Helper;
using com.nm.interfaces;
using com.nm.library.Factorys;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using com.nm.db;
using com.nm.library;
using com.nm.library.Helper;
using com.nm.models;
using com.nm.Security;

namespace BaseAPI
{
    public class LoginHandler : BaseHandler
    {

        #region LoginAPI
        
        /// <summary> 
        /// <param name="UserName">用户名（LoginID）</param>
        /// <param name="PassWord">MD5以后的密码</param>
        /// <returns></returns>
        [Description("账号登陆")]
        public ApiResult Login(
            [ParamDescription("用户账号")]string UserName,
            [ParamDescription("用户密码（MD5）")]string PassWord,
            [ParamDescription("用户密码")]string PassWord2,
            [ParamDescription("是否强制登录,0否,1是")]int ForceLogin = 0
            )
        {
            var userFactory = FactoryMaker.Get<IUserFactory>("user-facotry", "com.nm.db.MemberShipFactory,com.nm.db");
            //var loginUser = userFactory.Login(UserName, PassWord, PassWord2, Request.UserHostAddress, ForceLogin);
            var loginUser = userFactory.Login(UserName, PassWord);
            if (loginUser == null)
            {
                return Error("登陆失败");
            }
            var dc = new SysEntities();
            this.Session.Set("CurrentUserId", loginUser.UserId);
            this.Session.Set("CurrentRoleType", loginUser.RolesType);
            var company = GetCompany(loginUser.UserId, dc);
            //TODO:数据权限,暂屏蔽
            //Common.SetDataRights(this.UserId);
            var avatar = (from img in dc.vm_Avatar
                where img.UserID == loginUser.UserId
                orderby img.IsDefault descending
                select img.Url).FirstOrDefault();
            var configList = (from c in dc.sys_config
                              select c).ToList();
            loginUser.IsModifyPass = MD5.GetPassWord("1qaz2wsx").Equals(PassWord.ToUpper());
            return Success(new LoginUserData
            {
                UserId = loginUser.UserId,
                NickName = loginUser.NickName,
                Avatar = this.GetImageUrl(avatar, "http"),
                LoginID = loginUser.LoginId,
                Tel = loginUser.Tel,
                AccessToken = OnlineUsers.GetToken(),
                Refresh = userFactory.GetRefreshToken(loginUser),
                DeptId = loginUser.DeptId,
                RoleName = loginUser.RoleName,
                ConfigList = configList,
                IsModifyPass = loginUser.IsModifyPass,
                SysType = loginUser.SysType,
                CompanyName = company?.DeptContent,
                CompanyID = company?.CompanyID,
                //OnlineInfo = loginUser.OnlineInfo
            });
        }
        #endregion LoginAPI

        #region LoginByTokenAPI

        /// <summary> 
        /// <param name="UserName">用户名（LoginID）</param>
        /// <param name="PassWord">MD5以后的密码</param>
        /// <returns></returns>
        [Description("账号登陆")]
        public ApiResult LoginByToken(
            [ParamDescription("用户账号")]string UserName,
            [ParamDescription("单点登录系统Token")]string Token,
            [ParamDescription("单点登录系统用户ID")]string UserId
            )
        {
            var userFactory = FactoryMaker.Get<IUserFactory>("user-facotry", "com.nm.db.MemberShipFactory,com.nm.db");
            var loginUser = userFactory.Login(UserName, UserId, Token, Request.UserHostAddress);
            if (loginUser == null)
            {
                return Error("登陆失败");
            }
            var dc = new SysEntities();
            this.Session.Set("CurrentUserId", loginUser.UserId);
            var company = GetCompany(loginUser.UserId, dc);
            //Common.SetDataRights(this.UserId);
            var avatar = (from img in dc.vm_Avatar
                          where img.UserID == loginUser.UserId
                          orderby img.IsDefault descending
                          select img.Url).FirstOrDefault();
            var configList = (from c in dc.sys_config
                              select c).ToList();
            // loginUser.IsModifyPass = MD5.GetPassWord("1qaz2wsx").Equals(PassWord.ToUpper());
            return Success(new LoginUserData
            {
                UserId = loginUser.UserId,
                NickName = loginUser.NickName,
                Avatar = this.GetImageUrl(avatar, "http"),
                LoginID = loginUser.LoginId,
                Tel = loginUser.Tel,
                AccessToken = OnlineUsers.GetToken(),
                Refresh = userFactory.GetRefreshToken(loginUser),
                DeptId = loginUser.DeptId,
                RoleName = loginUser.RoleName,
                ConfigList = configList,
                IsModifyPass = loginUser.IsModifyPass,
                SysType = loginUser.SysType,
                CompanyName = company?.DeptContent,
                CompanyID = company?.CompanyID,
                OnlineInfo = loginUser.OnlineInfo
            });
        }

        #endregion LoginByTokenAPI

        /// <summary>
        /// 返回用户所属公司
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public CompanyData GetCompany(int userId, SysEntities dc)
        {
            if(dc==null) dc=new SysEntities();

            #region 从向拄下找,一般是集团用户
            var sql1 = $@"--查询树状结构某节点下的所有子节
                        with cte_child(deptid,parentid,DeptContent,CompanyID)
                        as
                        (
                            --起始条件 
                            select deptid,parentid,DeptContent,CompanyID
                            from sys_dept
                            where deptcode = (SELECT d.DeptCode FROM dbo.sys_users u
                            INNER JOIN dbo.sys_dept d ON u.DeptID=d.DeptID
                             WHERE UserID={userId}) --列出父节点查询条件
                            AND IsRemove=0
                            union all
                            --递归条件
                            select a.deptid,a.parentid,a.DeptContent,a.CompanyID
                            from sys_dept a
                            inner join 
                            cte_child b
                            on ( a.ParentID=b.deptid)  --根据查询到的父节点(a.Parent)，通过CTE递归查询出其子节点(b.ID)
                        )
                        select CompanyID,DeptContent from cte_child where ParentID =1 AND CompanyID IS NOT NULL ;";
            #endregion

            #region 从下往上往，一般是公司下的用户
            var sql2 = $@"--查询树状结构某节点下的所有子节
                        with cte_child(deptid,parentid,DeptContent,CompanyID)
                        as
                        (
                            --起始条件 
                            select deptid,parentid,DeptContent,CompanyID
                            from sys_dept
                            where deptcode = (SELECT d.DeptCode FROM dbo.sys_users u
                            INNER JOIN dbo.sys_dept d ON u.DeptID=d.DeptID
                             WHERE UserID={userId}) --列出父节点查询条件
                            AND IsRemove=0
                            union all
                            --递归条件
                            select a.deptid,a.parentid,a.DeptContent,a.CompanyID
                            from sys_dept a
                            inner join 
                            cte_child b
                            on ( a.deptid=b.ParentID)  --根据查询到的父节点(a.Parent)，通过CTE递归查询出其子节点(b.ID)
                        )
                        select CompanyID,DeptContent from cte_child where ParentID =1 AND CompanyID IS NOT NULL;";
            #endregion

            var query1 = dc.Database.SqlQuery<CompanyData>(sql1);
            var query2 = dc.Database.SqlQuery<CompanyData>(sql2);
            //合并两个集合并去重
            var result = query1.Union(query2).Distinct().ToList();
            //var companyId=string.Empty;
            //if (result.Count>0)
            //   companyId = string.Join(",", result);
            //return companyId;
            this.Session.Set("CurrentUserCompanyId", result.FirstOrDefault()?.CompanyID);
            var cesd = JsonHelper.CompanyIDExtrSourceDic()
                .ToDictionary(d => d.CompanyID, d => d.ExtrSource);
            var companyIDs = result.FirstOrDefault()?.CompanyID.Split(',');
            if (companyIDs == null) return result.FirstOrDefault();
            var cuesList = companyIDs.Select(item => cesd[item]).ToList();
            this.Session.Set("CurrentUserExtrSource", string.Join(",", cuesList));
            return result.FirstOrDefault();
        }

        /// <summary> 禁用
        /// <param name="UserName">用户名（LoginID）</param>
        /// <param name="PassWord">MD5以后的密码</param>
        /// <returns></returns>
        [Description("账号登陆")]
        public ApiResult Login_disable([ParamDescription("用户账号")]string UserName,
            [ParamDescription("用户密码（MD5）")]string PassWord)
        {
            var dc = new SysEntities();
            var user = dc.sys_users.FirstOrDefault(u => u.PassWord == PassWord
                       && (u.LoginAccount == UserName || u.Tel == UserName));
            if (user == null)
            {
                throw new Exception("您输入的用户名或密码错误,请重新输入！");
            }
            if (!user.IsEffective || user.IsRemove == true)
            {
                throw new Exception("您的账号已经被禁用，请与服务人员联系！");
            }
            try
            {
                this.SetCurrentUserId(user.UserID);
            }
            catch (Exception ex)
            {
                return Error(ex.Message);
            }
            this.Session.Set("UserName", user.UserName);
            this.Session.Set("CurrentUserId", user.UserID);

            UserInfo.UserID = user.UserID.ToString();
            return Success(new LoginUserData
            {
                UserId = user.UserID,
                NickName = user.UserName,
                //Avatar = this.GetImageUrl(UserInfo.CusImg),
                LoginID = user.LoginAccount,
                Tel = user.Tel,
                AccessToken = OnlineUsers.GetToken()
            });
        }

        [Description("刷新 用户Tokken")]
        [ReturnType(typeof(LoginUserData))]
        public ApiResult RefreshAccessToken(
           [ParamDescription("用户id")] string user,
           [ParamDescription("key")] string key)
        {
            var userFactory = FactoryMaker.Get<IUserFactory>("user-facotry", "com.nm.db.MemberShipFactory,com.nm.db");
            var userId = userFactory.GetUserIdFromRefres(key);
            using (var dc = new SysEntities())
            {
                var userPass = (from wahUser in dc.sys_users
                                where (wahUser.LoginAccount == user || wahUser.Tel == user) && wahUser.UserID == userId
                                select wahUser.PassWord).DefaultIfEmpty("").FirstOrDefault();
                return string.IsNullOrWhiteSpace(userPass) ? Error("您的账号输入有误") : Login(user, userPass,string.Empty);
            }
        }

        [MustLogin]
        [Description("退出登陆")]
        public ApiResult OutLogin()
        {
            try
            {
                Session.Set("CurrentUserId", 0);
                new MemberShipFactory().LoginOut();
            }
            catch (Exception ex)
            {
                return Error(ex.Message);
            }
            return Success(0);
        }

        public ApiResult G()
        {
            return NotDoneError();

        }
    }

    public class LoginUserData
    {
        [ParamDescription("用户ID")]
        public int UserId { get; set; }

        [ParamDescription("用户昵称")]
        public string NickName { get; set; }

        [ParamDescription("头像")]
        public string Avatar { get; set; }

        [ParamDescription("用户名（登陆用）")]
        public string LoginID { get; set; }

        [ParamDescription("手机号码")]
        public string Tel { get; set; }

        [ParamDescription("User AccessToken")]
        public string AccessToken { get; set; }

        [ParamDescription("RefreshToken 刷新用户token用的")]
        public string Refresh { get; set; }

        [ParamDescription("部门ID")]
        public int DeptId { get; set; }

        [ParamDescription("角色名称")]
        public string RoleName { get; set; }

        [ParamDescription("系统设置列表")]
        public IList<sys_config> ConfigList { get; set; }

        [ParamDescription("是否默认密码")]
        public bool IsModifyPass { get; set; }

        [ParamDescription("系统类型")]
        public string SysType { get; set; }

        [ParamDescription("公司名称")]
        public string CompanyName { get; set; }

        [ParamDescription("公司代码")]
        public string CompanyID { get; set; }
        [ParamDescription("在线用户信息")]
        public SsoOnlineInfo OnlineInfo { get; set; }
    }

    public class CompanyData
    {
        [ParamDescription("公司编码")]
        public string CompanyID { get; set; }

        [ParamDescription("公司名称")]
        public string DeptContent { get; set; }
    }
}
